package com.chen.Dome2reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectDome2 {
    @Test
    public void getClassInfo() {
        //目标：获取类的信息
        //1.反射第一步：获取Class对象
        Class c1 = Student.class;
        System.out.println(c1.getName());// 获取类的包名+类名
        System.out.println(c1.getSimpleName());// 获取类名

    }

    //2.获取类的构造方法
    @Test
    public void getConstructor() throws Exception {
        Class c1 = Dog.class;
        //获取构造器对象
        Constructor[] con = c1.getDeclaredConstructors();
        for (Constructor c : con) {
            System.out.println(c);
        }
        //获取单个构造器对象
        Constructor c2 = c1.getDeclaredConstructor();// 无参
        System.out.println(c2.getName() + "(" + c2.getParameterCount() + ")");

        Constructor c3 = c1.getDeclaredConstructor(String.class, int.class, String.class);// 有参
        System.out.println(c3.getName() + "(" + c3.getParameterCount() + ")");
//获取构造器的作用依然是创建对象
        //4.获取单个成员变量信息
        Field f1 = c1.getDeclaredField("name");
        System.out.println(f1.getName() + "(" + f1.getType().getName() + ")");
        //使用暴力强制访问（暴力反射）
        c2.setAccessible(true);// 暴力访问
        Dog d1 = (Dog) c2.newInstance();//Dog with modifiers "private
        System.out.println(d1);

        Dog d2 = (Dog) c3.newInstance("小黑", 2, "北京");
        System.out.println(d2);
        //获取成员变量的目的依旧是取值和赋值
        Dog d3 = new Dog("小花", 3, "上海");
        f1.setAccessible(true);// 暴力访问，直接绕过访问权限
        f1.set(d3,"小明");
        System.out.println(d3);

        String name = (String) f1.get(d3);
        System.out.println(name);


    }

    //3.获取类的成员变量并进行操作
    @Test
    public void getField() throws Exception {
        //目标：获取类的成员变量并进行操作
        Class c1 = Dog.class;
        Field[] fields = c1.getDeclaredFields();
        for (Field f : fields) {
            System.out.println(f.getName() + "(" + f.getType().getName() + ")");
        }


    }

    //5.获取类的成员方法
    @Test
    public void getMethod() throws Exception {
        Class c1 = Dog.class;
        Method[] methods = c1.getDeclaredMethods();
        for (Method m : methods) {
            System.out.println(m.getName() + "(" + m.getParameterCount() + ")");
        }
        Method m1 = c1.getDeclaredMethod("eat", String.class);// 有参
        System.out.println(m1.getName() + "(" + m1.getParameterCount() + ")");
        Method m2 = c1.getDeclaredMethod("eat");// 无参
        System.out.println(m2.getName() + "(" + m2.getParameterCount() + ")");

        //获取成员方法的目的依旧是调用方法
        Dog d1 = new Dog("小花", 3, "上海");
        m1.setAccessible(true);
        Object h = m1.invoke(d1, "骨头");
        System.out.println(h);

        m2.setAccessible(true);
        Object h2 = m2.invoke(d1);
        System.out.println(h2);


    }
}
